Welcome back.
We're now going to start scripting our local script for our GUI.
We need a script, all the functionality for our command line frame and the message frame that will
appear on our screen.
So if we take our admin GUI and put it inside of starter GUI so we can go ahead and take a look at it,
we're going to have the main frame that's going to act as our command line.
So let me move it up so it's visible on the screen.
So we'll set it to a position like 0.55.
This will be our command line where we can enter in our commands.
And we can see all of the commands listed out here that matches whatever we're typing inside of this
box.
And then we're also going to have a message frame to display any messages to the player when they,
you know, might fill out a command wrong or something happens during the command.
And we'll tween that to about the center of the screen.
So to get started, we're going to need a few services.
Of course we're going to need replicated storage.
We're going to need the player service.
We're also going to need the tween service to tween UI elements.
And then we're also going to need a service called the Context Action Service.
And the purpose of this service is for us to be able to listen for specific inputs on the client based
on different contexts.
So instead of having to use the user input service, which runs all of the time, we can instead use
a context and bind a specific function to listen for when a key is pressed.
And we can connect and disconnect that context action whenever we want in our script.
So it's actually a little bit better than having to use the user input service.
The service also allows us to only listen to those inputs when they are not observed by the game engine.
So for example, if we're listening for when a player presses the colon key on their keyboard, but
we only want to bring up the UI when you know they're they're doing nothing else on their screen.
So if they're typing in chat up here, we of course don't want to pop up this command line.
Well, the context, uh, the context action service automatically handles that for us.
Now, some variables we're going to need of course, is the admin assets folder.
So that's going to be in replicated storage.
And we're going to wait for that folder to replicate.
And then inside of that folder we're going to need the two events.
One is going to be that request remote function.
And then we're also going to need that communication remote event.
We're going to have a reference to the local player here.
So players dot local player.
We're going to want to require that module script in admin assets, which is all of our commands.
And then we also want to have access to the admin settings module script.
And then the next thing we need to do here is to make some references for the things inside of our guy.
So we want to reference the guy itself, which is just script dot parent.
We want to have a reference to the main frame or the command line.
We'll just call it main frame guy.
Wait for child main.
And then we could do the same thing for the scrolling frame that is inside of our main frame.
So we have a scrolling frame in here that we're going to fill up with commands.
And I've made these example commands here.
So we're just going to duplicate these and put them inside of our scrolling frame.
And they're going to display stuff like all the commands that match you know whatever.
So we'll have a command in here like this.
And it'll show up and it'll display to us all the commands that match whatever we're typing in here.
So main frame, wait for child scrolling frame.
We'll want to have a reference to that message frame as well.
We want to have a reference to our input box inside of our mainframe.
So mainframe Way.for child text box.
Only rename this to Input Box.
And then I want to have a reference to that example command here, so we can clone it and put it inside
of our scrolling frame for all the commands that match whatever we're typing.
So example command is equal to main frame.
Wait for child example command.
And then another thing I want to be able to store in this script is our rank.
So I'm going to call it my rank level.
And we're going to use our request event.
And we're going to invoke to the server to get our rank.
So we're asking the server, hey, return to us what our rank is inside of this script.
And that actually means we're going to have to go back to our admin handler.
So inside of our on server invoke function.
Um, the problem here is we should actually check this section right here inside of this context only
because we're requesting to get a rank and we're not passing a table here.
But since this if statement is here, it's going to check whether or not we pass a table.
And if we don't it's going to return false, which we don't want to happen.
We only want to check to see if there's a table here for specific contexts that require for us to pass
a table, like for executing a command.
So we're going to get rid of that here.
And instead we've placed it inside of this section of the if statement.
Otherwise we can get our rank and it's going to return to us the number that represents our rank.
Now let's go ahead and define some constants for our guy.
Some of the constants are going to be the different positions that our frames are going to be in when
they're visible and not visible on the screen.
So for our main frame, when it's visible on the screen, we're going to have it at a Y position of
0.55 scale.
And when it's not visible, it's going to be at a scale of one.
And then for the message frame, we're going to have it visible at 0.5 scale.
And when it's not visible, we'll just put it at something like -0.3.
So we don't see it on the screen anymore.
So let's go ahead and hard code those here.
We're going to have one called message frame.
And we'll call it visible equal to a new Udim 0.5 scale on the x axis.
Nothing on the x offset.
And then 0.5 on the y scale and nothing on the y offset.
And then we could do the same thing for when it is invisible or not visible.
And that was -0.3 and then zero.
And then we could do the same thing for our main frame.
So main frame visible is equal to a new dim two.
That's going to be 0.950 and then 0.55 for it to be visible.
And then when it's not visible.
Oops is a ball Utum 2.92.950.
And then it's, uh, one and then zero.
And then some other text will have in here I'm going to use.
Uh, we'll call this one Success Text, and we're going to set it to executed successfully.
Because what the plan is here is that when we have our main frame on the screen, when we type in a
command and hit enter, I want to replace this text that you see here in this text box.
So if I go to my text box and we scroll down to our placeholder text, I want to replace it with successfully
executed command to let them know that they, you know, successfully executed the command on their
end.
And then we can set it back to the default text of enter command here.
So we'll create another constant for that as well.
We'll call it uh original text.
And that's going to be equal to uh enter command here.
And then let me put this back to be invisible on the screen again at the Y scale of one.
Next up, we're going to need quite a few functions here.
Inside of our GUI.
One's going to be for getting all of the commands that we are authorized to use.
I'm going to call it Get Authorized authorized commands.
And it's just going to return to us a table of all the commands that we're authorized to use based on
our rank level.
We're going to have a function, I'm going to call it create command label.
And this is going to be for duplicating our example command text label and putting some text in it.
So we'll pass uh, some text to this function which will be a string.
And then we can set up, you know, our command label.
We'll have a function for clearing out all of the different text labels within our scrolling frame.
So I can call this function clear scrolling frame.
And then we're also going to have a function to update the scrolling frame.
I'm going to call it update scrolling frame.
And the purpose of this is to insert all of the different commands that match whatever we're typing
in the scrolling frame or inside of our text box.
So whenever we're typing stuff into our text box, we want to continually update whatever's going to
be inside of our scrolling frame to match whatever we're typing in the text box, right?
And the plan here for this function is that we're going to pass a table of all of the commands that
currently match whatever they're typing in the text box.
So we can call this table matching commands.
Now that means we're going to need a function to actually handle when the text gets changed within our
text box.
So we can call this function on text changed.
And in here we can do all the functionality for searching up all of the different commands that match,
and update our scrolling frame with those matching commands.
Another function we're going to need is to display a message on our screen using our message frame,
and that takes again, more text to put in our display message.
And then another function we're going to need is to listen for when that button inside of our message
label gets pressed.
So we'll call it on message frame button clicked.
Alrighty, now some events we're going to need to listen to.
First off, uh, with our input box, we want to listen for when a player hits enter and inputs text,
and we have to listen to an event called Focused Lost.
We're going to connect a function to this.
And this event passes to us a variable or a boolean that tells us whether or not the player pressed
enter when they lost focus of the text box.
So we can call this enter pressed.
And in here we can check whether or not they pressed enter, and if they did, we can go and try and
execute a command.
The next thing we want to listen to is when the input box.
And we're going to use the get property change signal going to get the text.
When this changes we're going to connect our on text change function.
And then for our message frame, we're going to wait for our text button that's inside of there, which
is that okay button you saw earlier.
And whenever that gets clicked by our mouse again we're going to connect our on message frame button.
Clicked function.
And then here we're going to use the Context action service.
And we're going to use a function in there called bind action.
So we can name this action whatever we would like.
I'm going to call this action uh tween command line.
And the function for this is going to tween the command line onto our screen.
Of course, there's a couple more things we need to pass to this function.
There is a boolean we have to pass called Create touch button.
And this is for mobile devices.
So whether or not it'll show a button on the screen of mobile devices.
Uh currently we don't care about mobile devices.
So I'm going to set this to false.
And then the last thing we need to pass here is the enum Keycode or enum user input type that represents
the input we need to bind.
So for this particular one we want to bind to the enum dot Keycode dot semicolon.
So whenever a player presses the semicolon and the internal game engine did not observe the input or
aka, they didn't use chat or anything else, then we're going to execute this lambda function in here.
The last event we need to listen to is our comms event.
So on client event we're going to connect a function to this.
And again we're going to get passed an action and any arguments to go with that action.
And if you remember inside of our admin handler when we use the fire client function, we want to tell
the player to display a message containing a table with the text of the message.
So we could put an if statement here of if action is equal to display message, then we can use our
display message function and pass args one.
And that means args one is a string.
So let's go ahead and start filling out these functions up here.
So it should be pretty easy for us to figure out what commands were authorized to use, because we're
storing our rank level here in this variable.
So I'm going to create a table called allowed.
And we're going to loop through every single command in pairs commands dot current commands.
So we're going into our commands module script.
And we're going to loop through every single command that exists in here.
And we're going to check to see if we have permission to use the command.
So if command dot minimum rank.
Minimum rank.
If it is greater than my rank level, then we're just going to continue looping because we don't have
access to this command.
However, if the rank is equal to or less than our rank, then we can insert this into our allow table.
So we'll insert this command into our table.
And then once we're done looping through all the commands, we can just return this allowed table at
the end.
And actually what I'll do right here is I'll create a variable, I'm going to call it Authorize commands.
And we're going to use our Get Authorized commands function to, you know, store all the commands we're
authorized to use.
And we're going to use this in a bit.
The next thing we want to fill out is creating a command label.
So this should be pretty easy as well.
All we need to do is create a clone of our command label or example command.
So example command we're going to clone it.
We're going to set the text inside of it equal to the text that is passed to this function.
And then we're going to set the parent equal to the scrolling frame.
And then you could also set the clone dot visibility to true.
Now to clear our scrolling frame again, this should be pretty simple.
We're going to loop through every single child of the scrolling frame, so we can do for every element
in Ipairs scrolling frame.
Get children.
What we'll do is we'll make sure that it is a text label, because inside of our scrolling frame is
a UI list layout, and we do not want to destroy this.
So if not element is a text label, then we're just going to continue looping.
Otherwise we can go ahead and destroy this element.
Pretty simple for that function.
The next function I want to do here is to update our scrolling frame.
So before we start inserting new commands inside of our scrolling frame, we need to first clear out
any other text label that was previously within our scrolling frame.
And then once we do that, we can loop through every single command in the matching commands parameter.
And what we could do with each one of these commands is we could create a clone of the example command
label, and then we can create a variable for the text we want to insert in there.
So we could first do admin settings.
We want to get the prefix.
And then we want to concatenate it with the commands dot usage.
And for this one we could just get the first usage that exists for the command.
So if our command was like set speed then the usage would appear as set speed in the string.
And then what we would do next is we would loop through every single parameter.
So every single parameter in ipairs command dot parameters.
We want to concatenate it to our text string.
So we could do text and concatenate it with, uh, inside of brackets.
We're going to put the type of this parameter and we're going to format it with the parameter type.
So if we have a command like set speed and we require first to pass a player and then a number, this
is what it's going to look like inside of our command line.
It's going to tell us okay you need to type out the command like this.
The first parameter is a player.
And then the second one is a number.
And then once we do that, all we need to do is call our create command label function and pass the
text we just created to it.
All right.
So the next function we need to fill out is our on text change function.
So we're going to have to get the text that is inside of our text box.
So I'm going to create a variable.
I'll just call it uh search text.
And it's going to be a table containing all of the different string elements that we've typed out inside
of the text box.
So again we're going to use the string dot split command.
And we're going to split up all of the text that is inside of our input box by a space.
And we're actually going to make this lowercase again to stay consistent.
And then what we could do here is we could see if the search text and see if the very first element
in there is an empty table.
So let's say they didn't put anything at all.
Well then what we want to do is we just want to clear out the scrolling frame and then return out of
the function.
So for example, if a person is typing in there and they're typing out something like colon, it's going
to display all of the commands in our game.
And then when they hit backspace we want to clear out the scrolling frame, meaning that the first text
there is nothing.
Right.
So we want to clear out the scrolling frame and display nothing on their screen.
Otherwise I'm going to create a variable called matching commands.
And what we're going to do is we're going to loop through every single command in that variable we created,
which was authorized commands.
And we're going to do is first, if the search text.
Uh, the first element is equal to just a colon.
So let's say they only typed a colon into the text box.
Then what we could do is we could just set matching commands equal to authorized commands, and then
we'll just break out of this loop, because there's no need to loop through every other single function
if the only thing they typed in is colon.
And because they typed in colon, that means we're going to display to them all of the authorized commands
they're able to use.
Otherwise, if they typed more than a colon, then we're going to loop through every single usage and
ipairs command dot usage, because we need to check if they're actually typing out the correct usage
for this particular command if it matches or not.
Right.
So if admin settings dot prefix, concatenate it with this usage.
And then we're going to get a substring of it.
From the first index all the way to however much they typed inside of our text box.
So the length of search text one.
So search text one, you could use length.
Or we could also do.
Cohen, Len.
Here for length.
If it is not equal to search text one, then we're going to continue looping.
So we're basically just in a substring of whatever this command's usage is.
And if it's not equal to what we've typed out inside of our command line, then we're going to continue
looping to the next usage.
And if that doesn't match, we'll loop to the next usage.
If that doesn't match, then we're going to loop to the next function and then check all those usages
and so on and so forth.
But if it does match, then we can insert this command inside of matching commands.
And then we can go ahead and just break out of this loop and move on to the next command.
And then once we're done doing all that, we can call our update scrolling frame function and pass the
matching commands table.
And then this function is going to go ahead and loop through all of those commands and create clones
of those text labels and, you know, insert it into, uh, the scrolling frame.
And actually, since this create command label is already creating a clone of our text label, we don't
need to do it here.
I'm not sure why I included that.
Okay, so for the next function here, uh, what do we want to do when we want to display a message
on the player's screen?
Well, that's pretty simple.
First we want to set the message frame dot position equal to the message frame invisible.
So first we want to make it not visible on the screen.
Then we want to set the text inside of it.
So the message label dot text equal to the text passed to this function.
And then we're going to use the tween service and create a new tween on our message frame.
And we can make this tween last something like, uh, I don't know, 0.5 seconds and we can make it
a little fancy by using a different enemies style like sign.
And we want to set the position of this message frame equal to the message frame visible.
And then we can call the play function on this tween.
The next thing we want to do is what do we want to do when that button inside of our message frame gets
clicked?
Well, we want to hide the message frame.
So we're going to use the tween service and create a new tween on our message frame.
Again we can do tween info dot new 0.5 seconds and do enum dot easing style sign.
And this time, instead of setting the position to be visible, we want to set the position to be not
visible.
So message frame invisible and then we just play this tween.
All right.
We're all good to go here.
Let's go ahead and start filling out our event handlers.
So the first thing we need to check here, when we lose focus in our input box, is whether or not the
player pressed enter on their keyboard.
So if they did not press enter, then we're just going to return because we don't care.
If they did press enter, then what we need to do is we need to get the text that is inside of their
input box.
So input box, dot text.
And then we can set the input box dot text to nothing.
And then once that's done we're going to use our request event and invoke to the server to execute a
command.
So execute command.
And that command is going to be whatever text they entered into that text box.
And again, this is going to return back to us a boolean of whether or not we were successful, and
then a message or an error message if we were not successful.
So if we were not successful in executing this function, then we can display a message on the player's
screen using that result variable.
Otherwise, if we were successful in executing the command, then we can set the input box placeholder
text equal to the success text.
And then we can wait something like, I don't know, three seconds.
And if the input box dot placeholder text is still equal to the success text, then we can set input
box dot placeholder text equal to original text.
Alrighty, now, the last function we need to fill out right here is for our Context Action Service.
So we're binding this function to be our action for when we hit a semicolon on our keyboard.
What do we want to do when a player hits a semicolon on their keyboard.
Well, we want to tween our command line to be visible or invisible on the screen.
So if our main frame dot position is equal to main frame visible.
So if it's already visible on our screen and the player presses a semicolon, well, that means we want
to make the frame no longer visible.
So we can use the tween service to create a new tween on our main frame.
Tween info dot new.
We can do 0.5 seconds and we can do something fancy like enum dot easing style dot sign.
And we want to set the position equal to the main frame invisible.
And then we can just play this tween.
Otherwise, if the main frame dot position is equal to main frame invisible, then that means we want
to tween the main frame to be visible.
So tween service create on our main frame tween info dot new point five enum using style sign and we
want to tween the position to be visible.
And then we can play this tween as well.
And guess what?
That's it.
We are ready to go with our local script, and that means we should be able to test out whether or not
our guy is working.
And one little extra thing you can do down here is that, let's say in our guy, you forgot to set the
main frame and the visible frame back to their hidden position.
Let's say they were visible on our screen right now.
Well, when the script runs, we can go ahead and make sure to set the main frame dot position equal
to main frame invisible and do the same thing for the message frame.
Uh, message frame invisible.
There we go.
Now we can go ahead and take our admin guy and place it back inside of admin assets, because again,
our server script has to clone it from this folder.
And since I did put inside of the settings module script my id.
So since I put my ID in here, it's going to see that I am an admin and it should give me the guy on
my end.
So if we go and test and play out our game here.
We get no errors.
That's good.
If I go ahead and hit semicolon.
Look at that.
We get our command line to show up.
And then if I hit semicolon again, our command line disappears.
Now let's say I have my chat open right now.
If I hit semicolon look at that.
Our command line does not move up because the game recognizes that the game engine is currently observing
our input inside of the chat box.
But once I get out of the chat box and then hit semicolon, our command line pops up.
Now, the next thing we should test is when we press colon in here, it should show us all the commands
we're able to use.
So if I do colon.
There we go.
It's showing us currently that the only command we have is set speed and showing us it takes a player
and a number.
So let me actually go ahead and stop this test real quick.
And I'm going to fill this up with a bunch of different random commands real quick.
So I'll have example one.
Example two.
Example three.
And for this usage we could do like set health.
And for this one we could do something like fling.
And then we'll get rid of the second parameter for this one.
Again we're just doing this as an example.
But if we go ahead and go back and test our game.
When we go type out a colon in here, boom.
It shows us we have three commands.
We have access to set speed, which takes a player, and a number fling, which just takes a player,
and then set health, which takes a player and a number.
And if I continue typing, so if I type in set, it's going to get rid of fling, because fling is not
matching our command.
Uh, but it looks like it's being a little weird.
But if we do, like, set this and then we do set speed, of course, it's only going to show us set
speed.
If we do set health, it's going to only show us set health and so on.
But it appears it's still showing our fling function.
And that's probably because if we go to our fling function here that we just made as an example, right.
We also set it to have a usage of speed.
So if I get rid of that and then we go back and test.
Again.
If I pull up my command line, put colon and then press S, there we go.
We only get shown set speed, set health.
And as I continue typing, it's only going to show us the commands that currently match this text that
we've entered into our command line.
So it continuously updates.
And again, once we get rid of the colon, it clears out the command line and nothing else shows up
in here.
Okay.
So we're finished scripting the client here.
And in the next lecture we're going to continue testing our admin system by creating some commands.
So I'll go ahead and see you there.